<!DOCTYPE html><html lang="zh-CN,en,default"><head hexo-theme="https://github.com/volantis-x/hexo-theme-volantis/tree/4.3.1"><meta charset="utf-8"><meta http-equiv="x-dns-prefetch-control" content="on"><link rel="dns-prefetch" href="https://cdn.jsdelivr.net"><link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin><meta name="renderer" content="webkit"><meta name="force-rendering" content="webkit"><meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"><meta name="HandheldFriendly" content="True"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"><link rel="preload" href="/css/first.css" as="style"><title>Spring学习笔记-AOP基本介绍 - Tang&#39;s blog.</title><meta name="keywords" content="Spring"><meta name="description" content="AOP：Aspect Oriented Programming  面向切面编程
OOP：Object Oriented Programming  面向对象编程"><link rel="alternate" href="/atom.xml" title="Tang's blog." type="application/atom+xml"><meta name="msapplication-TileColor" content="#ffffff"><meta name="msapplication-config" content="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/blog/favicon/browserconfig.xml"><meta name="theme-color" content="#ffffff"><link rel="apple-touch-icon" sizes="180x180" href="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/img/favicon/cf_1o_180x180.png"><link rel="icon" type="image/png" sizes="32x32" href="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/img/favicon/cf_1o_32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/img/favicon/cf_1o_16x16.png"><link rel="manifest" href="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/img/favicon/manifest2.json"><link rel="mask-icon" href="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/img/favicon/cf_image2vector.svg" color="#5bbad5"><link rel="shortcut icon" href="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/img/favicon/32favicon32.ico"><link rel="stylesheet" href="/css/first.css"><link rel="stylesheet" href="/css/style.css" media="print" onload='this.media="all",this.onload=null'><noscript><link rel="stylesheet" href="/css/style.css"></noscript><script id="loadcss"></script><script>window.MSInputMethodContext&&document.documentMode&&document.write('<style>html{overflow-x: hidden !important;overflow-y: hidden !important;}.kill-ie{text-align:center;height: 100%;margin-top: 15%;margin-bottom: 5500%;}</style><div class="kill-ie"><h1><b>抱歉，您的浏览器无法访问本站</b></h1><h3>微软已经于2016年终止了对 Internet Explorer (IE) 10 及更早版本的支持，<br/>继续使用存在极大的安全隐患，请使用当代主流的浏览器进行访问。</h3><br/><a target="_blank" rel="noopener external nofollow noreferrer" href="https://www.microsoft.com/zh-cn/WindowsForBusiness/End-of-IE-support"><strong>了解详情 ></strong></a></div>')</script><noscript><style>html{overflow-x:hidden!important;overflow-y:hidden!important}.kill-noscript{text-align:center;height:100%;margin-top:15%;margin-bottom:5500%}</style><div class="kill-noscript"><h1><b>抱歉，您的浏览器无法访问本站</b></h1><h3>本页面需要浏览器支持（启用）JavaScript</h3><br> <a target="_blank" rel="noopener external nofollow noreferrer" href="https://www.baidu.com/s?wd=启用JavaScript"><strong>了解详情 ></strong></a></div></noscript></head><body><header id="l_header" class="l_header always shadow blur show"><div class="container"><div id="wrapper"><div class="nav-sub"><p class="title"></p><ul class="switcher nav-list-h m-phone" id="pjax-header-nav-list"><li><a id="s-comment" class="fas fa-comments fa-fw" target="_self" href="javascript:void(0)" rel="external nofollow noreferrer"></a></li><li><a id="s-toc" class="s-toc fas fa-list fa-fw" target="_self" href="javascript:void(0)" rel="external nofollow noreferrer"></a></li></ul></div><div class="nav-main"> <a class="title flat-box" target="_self" href="/"><img no-lazy class="logo" src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/img/cover/fav/cf_o1x64.jpg"></a><div class="menu navigation"><ul class="nav-list-h m-pc"><li><a class="menuitem flat-box faa-parent animated-hover" href="/" id="home"><i class="fas fa-home fa-fw"></i> Home</a></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-th-list fa-fw"></i> Articles</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/categories/" id="categories"><i class="fas fa-folder-open fa-fw"></i> Categories</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/tags/" id="tags"><i class="fas fa-tags fa-fw"></i> Tags</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/archives/" id="archives"><i class="fas fa-archive fa-fw"></i> Archives</a></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-fan faa-spin animated fa-fw"></i> Play</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/catchTheCat/" id="catchTheCat"><i class="fas fa-cat faa-wrench animated-hover fa-fw"></i> Chat Noir</a></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-cog fa-spin fa-fw"></i> Tools</a><ul class="list-v"><li><a class="menuitem flat-box header toggle-mode-btn"><i class="fas fa-moon fa-fw"></i> 暗黑模式</a></li><li></li><li><a class="menuitem flat-box"><i class="fas fa-compact-disc fa-fw music"></i> Music</a><ul class="list-v"><li><div class="aplayer-container"><meting-js theme="#1BCDFC" autoplay="false" volume="0.7" loop="all" order="list" fixed="false" list-max-height="320px" server="netease" type="playlist" id="5472211102" list-folded="true"></meting-js></div></li></ul></li><li></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-info-circle fa-fw"></i> Me</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/about/" id="about"><i class="fas fa-ellipsis-v fa-fw"></i> About</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="https://aner1001.gitee.io/resume/" target="_blank" id="https:aner1001giteeioresume"><i class="fas fa-clock fa-fw"></i> Resume</a></li></ul></li></ul></div><div id="tp-weather-widget"></div><script>!function(e,t,n,a,i,o,c,r){r=function(){o=t.createElement(n),c=t.getElementsByTagName(n)[0],o.src=i,o.charset="utf-8",o.async=1,c.parentNode.insertBefore(o,c)},e.SeniverseWeatherWidgetObject=a,e[a]||(e[a]=function(){(e[a].q=e[a].q||[]).push(arguments)}),e[a].l=+new Date,e.attachEvent?e.attachEvent("onload",r):e.addEventListener("load",r,!1)}(window,document,"script","SeniverseWeatherWidget","//cdn.sencdn.com/widget2/static/js/bundle.js?t="+parseInt(((new Date).getTime()/1e8).toString(),10)),window.SeniverseWeatherWidget("show",{flavor:"slim",location:"WTW3SJ5ZBJUY",geolocation:!0,language:"zh-Hans",unit:"c",theme:"auto",token:"563a4097-8461-469b-ac30-123bac0010d1",hover:"enabled",container:"tp-weather-widget"})</script><div class="m_search"><form name="searchform" class="form u-search-form"><i class="icon fas fa-search fa-fw"></i> <input type="text" class="input u-search-input" placeholder="Search..."></form></div><ul class="switcher nav-list-h m-phone"><li><a class="s-search fas fa-search fa-fw" target="_self" href="javascript:void(0)" rel="external nofollow noreferrer"></a></li><li><a class="s-menu fas fa-bars fa-fw" target="_self" href="javascript:void(0)" rel="external nofollow noreferrer"></a><ul class="menu-phone list-v navigation white-box"><li><a class="menuitem flat-box faa-parent animated-hover" href="/" id="home"><i class="fas fa-home fa-fw"></i> Home</a></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-th-list fa-fw"></i> Articles</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/categories/" id="categories"><i class="fas fa-folder-open fa-fw"></i> Categories</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/tags/" id="tags"><i class="fas fa-tags fa-fw"></i> Tags</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/archives/" id="archives"><i class="fas fa-archive fa-fw"></i> Archives</a></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-fan faa-spin animated fa-fw"></i> Play</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/catchTheCat/" id="catchTheCat"><i class="fas fa-cat faa-wrench animated-hover fa-fw"></i> Chat Noir</a></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-cog fa-spin fa-fw"></i> Tools</a><ul class="list-v"><li><a class="menuitem flat-box header toggle-mode-btn"><i class="fas fa-moon fa-fw"></i> 暗黑模式</a></li><li></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-info-circle fa-fw"></i> Me</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/about/" id="about"><i class="fas fa-ellipsis-v fa-fw"></i> About</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="https://aner1001.gitee.io/resume/" target="_blank" id="https:aner1001giteeioresume"><i class="fas fa-clock fa-fw"></i> Resume</a></li></ul></li></ul></li></ul></div></div></div></header><div id="l_body"><div id="l_cover"><div id="full" class="cover-wrapper post blank" style="display:none"><div id="cover-backstretch"></div><div id="scroll-down" style="display:none"><i class="fa fa-chevron-down scroll-down-effects"></i></div></div></div><div id="safearea"><div class="body-wrapper" id="pjax-container"><div class="l_main"><article class="article post white-box reveal md shadow article-type-post" id="post" itemscope itemprop="blogPost"><div class="article-meta" id="top"><h1 class="title"> Spring学习笔记-AOP基本介绍</h1><div class="new-meta-box"><div class="new-meta-item author"> <a class="author" href="/" rel="nofollow"><img no-lazy src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/img/cover/fav/cf_1o_x16.jpg"><p>汤晔飞</p></a></div><div class="new-meta-item category"><a class="notlink"><i class="fas fa-folder-open fa-fw" aria-hidden="true"></i> <a class="category-link" href="/categories/%E6%8A%80%E6%9C%AF%E7%9F%A5%E8%AF%86/">技术知识</a><span class="sep"></span><a class="category-link" href="/categories/%E6%8A%80%E6%9C%AF%E7%9F%A5%E8%AF%86/Java/">Java</a></a></div><div class="new-meta-item date"><a class="notlink"><i class="fas fa-calendar-alt fa-fw" aria-hidden="true"></i><p>发布于：2021年2月25日</p></a></div><div class="new-meta-item browse leancloud"><a class="notlink"><div id="lc-pv" data-title="Spring学习笔记-AOP基本介绍" data-path="/posts/2021/02/25/d257d0f10a3c/"><i class="fas fa-eye fa-fw" aria-hidden="true"></i><span id="number"><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span> 次浏览</div></a></div></div></div><p>AOP：Aspect Oriented Programming 面向切面编程<br> OOP：Object Oriented Programming 面向对象编程</p><span id="more"></span><blockquote><p>面向切面编程：基于OOP基础之上新的编程思想，OOP面向的主要对象是类，而AOP面向的主要对象是切面，在处理日志、安全管理、事务管理等方面有非常重要的作用。AOP是Spring中重要的核心点，虽然IOC容器没有依赖AOP，但是AOP提供了非常强大的功能，用来对IOC做补充。通俗点说的话就是在程序运行期间，将<strong>某段代码动态切入</strong>到<strong>指定方法</strong>的<strong>指定位置</strong>进行运行的这种编程方式。</p></blockquote><h2 id="1-AOP的概念"><a class="header-anchor" href="#1-AOP的概念">☀</a>1.AOP的概念</h2><h3 id="为什么要引入AOP"><a class="header-anchor" href="#为什么要引入AOP">☀</a>为什么要引入AOP?</h3><p>Calculator.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.inter;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">Calculator</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">add</span><span class="params">(<span class="type">int</span> i,<span class="type">int</span> j)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">sub</span><span class="params">(<span class="type">int</span> i,<span class="type">int</span> j)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">mult</span><span class="params">(<span class="type">int</span> i,<span class="type">int</span> j)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">div</span><span class="params">(<span class="type">int</span> i,<span class="type">int</span> j)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>MyCalculator.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.inter;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyCalculator</span> <span class="keyword">implements</span> <span class="title class_">Calculator</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">add</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i + j;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">sub</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i - j;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">mult</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i * j;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">div</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i / j;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>MyTest.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyTest</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> SQLException &#123;</span><br><span class="line">        <span class="type">MyCalculator</span> <span class="variable">myCalculator</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyCalculator</span>();</span><br><span class="line">        System.out.println(myCalculator.add(<span class="number">1</span>, <span class="number">2</span>));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>​ 此代码非常简单，就是基础的javase的代码实现，此时如果需要添加日志功能应该怎么做呢，只能在每个方法中添加日志输出，同时如果需要修改的话会变得非常麻烦。</p><p>MyCalculator.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.inter;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyCalculator</span> <span class="keyword">implements</span> <span class="title class_">Calculator</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">add</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;add 方法开始执行，参数为：&quot;</span>+i+<span class="string">&quot;,&quot;</span>+j);</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i + j;</span><br><span class="line">        System.out.println(<span class="string">&quot;add 方法开始完成结果为：&quot;</span>+result);</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">sub</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;sub 方法开始执行，参数为：&quot;</span>+i+<span class="string">&quot;,&quot;</span>+j);</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i - j;</span><br><span class="line">        System.out.println(<span class="string">&quot;add 方法开始完成结果为：&quot;</span>+result);</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">mult</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;mult 方法开始执行，参数为：&quot;</span>+i+<span class="string">&quot;,&quot;</span>+j);</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i * j;</span><br><span class="line">        System.out.println(<span class="string">&quot;add 方法开始完成结果为：&quot;</span>+result);</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">div</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;div 方法开始执行，参数为：&quot;</span>+i+<span class="string">&quot;,&quot;</span>+j);</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i / j;</span><br><span class="line">        System.out.println(<span class="string">&quot;add 方法开始完成结果为：&quot;</span>+result);</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>​ 可以考虑将日志的处理抽象出来，变成工具类来进行实现：</p><p>LogUtil.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.util;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogUtil</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">start</span><span class="params">(Object ... objects)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;XXX方法开始执行，使用的参数是：&quot;</span>+ Arrays.asList(objects));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">stop</span><span class="params">(Object ... objects)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;XXX方法执行结束，结果是：&quot;</span>+ Arrays.asList(objects));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>MyCalculator.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.inter;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.mashibing.util.LogUtil;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyCalculator</span> <span class="keyword">implements</span> <span class="title class_">Calculator</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">add</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        LogUtil.start(i,j);</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i + j;</span><br><span class="line">        LogUtil.stop(result);</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">sub</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        LogUtil.start(i,j);</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i - j;</span><br><span class="line">        LogUtil.stop(result);</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">mult</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        LogUtil.start(i,j);</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i * j;</span><br><span class="line">        LogUtil.stop(result);</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">div</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        LogUtil.start(i,j);</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i / j;</span><br><span class="line">        LogUtil.stop(result);</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>​ 按照上述方式抽象之后，代码确实简单很多，但是大家应该已经发现在输出的信息中并不包含具体的方法名称，我们更多的是想要在程序运行过程中动态的获取方法的名称及参数、结果等相关信息，此时可以通过使用<strong>动态代理</strong>的方式来进行实现。</p><p>CalculatorProxy.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.proxy;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.mashibing.inter.Calculator;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.InvocationHandler;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.InvocationTargetException;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Method;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Proxy;</span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 帮助Calculator生成代理对象的类</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CalculatorProxy</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     *  为传入的参数对象创建一个动态代理对象</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> calculator 被代理对象</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> Calculator <span class="title function_">getProxy</span><span class="params">(<span class="keyword">final</span> Calculator calculator)</span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//被代理对象的类加载器</span></span><br><span class="line">        <span class="type">ClassLoader</span> <span class="variable">loader</span> <span class="operator">=</span> calculator.getClass().getClassLoader();</span><br><span class="line">        <span class="comment">//被代理对象的接口</span></span><br><span class="line">        Class&lt;?&gt;[] interfaces = calculator.getClass().getInterfaces();</span><br><span class="line">        <span class="comment">//方法执行器，执行被代理对象的目标方法</span></span><br><span class="line">        <span class="type">InvocationHandler</span> <span class="variable">h</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">InvocationHandler</span>() &#123;</span><br><span class="line">            <span class="comment">/**</span></span><br><span class="line"><span class="comment">             *  执行目标方法</span></span><br><span class="line"><span class="comment">             * <span class="doctag">@param</span> proxy 代理对象，给jdk使用，任何时候都不要操作此对象</span></span><br><span class="line"><span class="comment">             * <span class="doctag">@param</span> method 当前将要执行的目标对象的方法</span></span><br><span class="line"><span class="comment">             * <span class="doctag">@param</span> args 这个方法调用时外界传入的参数值</span></span><br><span class="line"><span class="comment">             * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">             * <span class="doctag">@throws</span> Throwable</span></span><br><span class="line"><span class="comment">             */</span></span><br><span class="line">            <span class="keyword">public</span> Object <span class="title function_">invoke</span><span class="params">(Object proxy, Method method, Object[] args)</span> <span class="keyword">throws</span> Throwable &#123;</span><br><span class="line">                <span class="comment">//利用反射执行目标方法,目标方法执行后的返回值</span></span><br><span class="line"><span class="comment">//                System.out.println(&quot;这是动态代理执行的方法&quot;);</span></span><br><span class="line">                <span class="type">Object</span> <span class="variable">result</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    System.out.println(method.getName()+<span class="string">&quot;方法开始执行，参数是：&quot;</span>+ Arrays.asList(args));</span><br><span class="line">                    result = method.invoke(calculator, args);</span><br><span class="line">                    System.out.println(method.getName()+<span class="string">&quot;方法执行完成，结果是：&quot;</span>+ result);</span><br><span class="line">                &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">                    System.out.println(method.getName()+<span class="string">&quot;方法出现异常：&quot;</span>+ e.getMessage());</span><br><span class="line">                &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">                    System.out.println(method.getName()+<span class="string">&quot;方法执行结束了......&quot;</span>);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="comment">//将结果返回回去</span></span><br><span class="line">                <span class="keyword">return</span> result;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        <span class="type">Object</span> <span class="variable">proxy</span> <span class="operator">=</span> Proxy.newProxyInstance(loader, interfaces, h);</span><br><span class="line">        <span class="keyword">return</span> (Calculator) proxy;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>​ 我们可以看到这种方式更加灵活，而且不需要在业务方法中添加额外的代码，这才是常用的方式。如果想追求完美的同学，还可以使用上述的日志工具类来完善。</p><p>LogUtil.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.util;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Method;</span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogUtil</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">start</span><span class="params">(Method method, Object ... objects)</span>&#123;</span><br><span class="line"><span class="comment">//        System.out.println(&quot;XXX方法开始执行，使用的参数是：&quot;+ Arrays.asList(objects));</span></span><br><span class="line">        System.out.println(method.getName()+<span class="string">&quot;方法开始执行，参数是：&quot;</span>+ Arrays.asList(objects));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">stop</span><span class="params">(Method method,Object ... objects)</span>&#123;</span><br><span class="line"><span class="comment">//        System.out.println(&quot;XXX方法执行结束，结果是：&quot;+ Arrays.asList(objects));</span></span><br><span class="line">        System.out.println(method.getName()+<span class="string">&quot;方法开始执行，参数是：&quot;</span>+ Arrays.asList(objects));</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">logException</span><span class="params">(Method method,Exception e)</span>&#123;</span><br><span class="line">        System.out.println(method.getName()+<span class="string">&quot;方法出现异常：&quot;</span>+ e.getMessage());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">end</span><span class="params">(Method method)</span>&#123;</span><br><span class="line">        System.out.println(method.getName()+<span class="string">&quot;方法执行结束了......&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>CalculatorProxy.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.proxy;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.mashibing.inter.Calculator;</span><br><span class="line"><span class="keyword">import</span> com.mashibing.util.LogUtil;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.InvocationHandler;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.InvocationTargetException;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Method;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Proxy;</span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 帮助Calculator生成代理对象的类</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CalculatorProxy</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     *  为传入的参数对象创建一个动态代理对象</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> calculator 被代理对象</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> Calculator <span class="title function_">getProxy</span><span class="params">(<span class="keyword">final</span> Calculator calculator)</span>&#123;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment">//被代理对象的类加载器</span></span><br><span class="line">        <span class="type">ClassLoader</span> <span class="variable">loader</span> <span class="operator">=</span> calculator.getClass().getClassLoader();</span><br><span class="line">        <span class="comment">//被代理对象的接口</span></span><br><span class="line">        Class&lt;?&gt;[] interfaces = calculator.getClass().getInterfaces();</span><br><span class="line">        <span class="comment">//方法执行器，执行被代理对象的目标方法</span></span><br><span class="line">        <span class="type">InvocationHandler</span> <span class="variable">h</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">InvocationHandler</span>() &#123;</span><br><span class="line">            <span class="comment">/**</span></span><br><span class="line"><span class="comment">             *  执行目标方法</span></span><br><span class="line"><span class="comment">             * <span class="doctag">@param</span> proxy 代理对象，给jdk使用，任何时候都不要操作此对象</span></span><br><span class="line"><span class="comment">             * <span class="doctag">@param</span> method 当前将要执行的目标对象的方法</span></span><br><span class="line"><span class="comment">             * <span class="doctag">@param</span> args 这个方法调用时外界传入的参数值</span></span><br><span class="line"><span class="comment">             * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">             * <span class="doctag">@throws</span> Throwable</span></span><br><span class="line"><span class="comment">             */</span></span><br><span class="line">            <span class="keyword">public</span> Object <span class="title function_">invoke</span><span class="params">(Object proxy, Method method, Object[] args)</span> <span class="keyword">throws</span> Throwable &#123;</span><br><span class="line">                <span class="comment">//利用反射执行目标方法,目标方法执行后的返回值</span></span><br><span class="line"><span class="comment">//                System.out.println(&quot;这是动态代理执行的方法&quot;);</span></span><br><span class="line">                <span class="type">Object</span> <span class="variable">result</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    LogUtil.start(method,args);</span><br><span class="line">                    result = method.invoke(calculator, args);</span><br><span class="line">                    LogUtil.stop(method,args);</span><br><span class="line">                &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">                    LogUtil.logException(method,e);</span><br><span class="line">                &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">                    LogUtil.end(method);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="comment">//将结果返回回去</span></span><br><span class="line">                <span class="keyword">return</span> result;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        <span class="type">Object</span> <span class="variable">proxy</span> <span class="operator">=</span> Proxy.newProxyInstance(loader, interfaces, h);</span><br><span class="line">        <span class="keyword">return</span> (Calculator) proxy;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>​ 很多同学看到上述代码之后可能感觉已经非常完美了，但是要说明的是，这种动态代理的实现方式调用的是jdk的基本实现，如果需要代理的目标对象没有实现任何接口，那么是无法为他创建代理对象的，这也是致命的缺陷。而在Spring中我们可以不编写上述如此复杂的代码，只需要利用AOP，就能够轻轻松松实现上述功能，当然，Spring AOP的底层实现也依赖的是动态代理。</p><h3 id="AOP的核心概念及术语"><a class="header-anchor" href="#AOP的核心概念及术语">☀</a>AOP的核心概念及术语</h3><ul><li>切面（Aspect）: 指关注点模块化，这个关注点可能会横切多个对象。事务管理是企业级Java应用中有关横切关注点的例子。 在Spring AOP中，切面可以使用通用类基于模式的方式（schema-based approach）或者在普通类中以<code>@Aspect</code>注解（@AspectJ 注解方式）来实现。</li><li>连接点（Join point）: 在程序执行过程中某个特定的点，例如某个方法调用的时间点或者处理异常的时间点。在Spring AOP中，一个连接点总是代表一个方法的执行。</li><li>通知（Advice）: 在切面的某个特定的连接点上执行的动作。通知有多种类型，包括“around”, “before” and “after”等等。通知的类型将在后面的章节进行讨论。 许多AOP框架，包括Spring在内，都是以拦截器做通知模型的，并维护着一个以连接点为中心的拦截器链。</li><li>切点（Pointcut）: 匹配连接点的断言。通知和切点表达式相关联，并在满足这个切点的连接点上运行（例如，当执行某个特定名称的方法时）。切点表达式如何和连接点匹配是AOP的核心：Spring默认使用AspectJ切点语义。</li><li>引入（Introduction）: 声明额外的方法或者某个类型的字段。Spring允许引入新的接口（以及一个对应的实现）到任何被通知的对象上。例如，可以使用引入来使bean实现 <code>IsModified</code>接口， 以便简化缓存机制（在AspectJ社区，引入也被称为内部类型声明（inter））。</li><li>目标对象（Target object）: 被一个或者多个切面所通知的对象。也被称作被通知（advised）对象。既然Spring AOP是通过运行时代理实现的，那么这个对象永远是一个被代理（proxied）的对象。</li><li>AOP代理（AOP proxy）:AOP框架创建的对象，用来实现切面契约（aspect contract）（包括通知方法执行等功能）。在Spring中，AOP代理可以是JDK动态代理或CGLIB代理。</li><li>织入（Weaving）: 把切面连接到其它的应用程序类型或者对象上，并创建一个被被通知的对象的过程。这个过程可以在编译时（例如使用AspectJ编译器）、类加载时或运行时中完成。 Spring和其他纯Java AOP框架一样，是在运行时完成织入的。</li></ul><h3 id="AOP的通知类型"><a class="header-anchor" href="#AOP的通知类型">☀</a>AOP的通知类型</h3><ul><li>前置通知（Before advice）: 在连接点之前运行但无法阻止执行流程进入连接点的通知（除非它引发异常）。</li><li>后置返回通知（After returning advice）:在连接点正常完成后执行的通知（例如，当方法没有抛出任何异常并正常返回时）。</li><li>后置异常通知（After throwing advice）: 在方法抛出异常退出时执行的通知。</li><li>后置通知（总会执行）（After (finally) advice）: 当连接点退出的时候执行的通知（无论是正常返回还是异常退出）。</li><li>环绕通知（Around Advice）:环绕连接点的通知，例如方法调用。这是最强大的一种通知类型，。环绕通知可以在方法调用前后完成自定义的行为。它可以选择是否继续执行连接点或直接返回自定义的返回值又或抛出异常将执行结束。</li></ul><h3 id="AOP的应用场景"><a class="header-anchor" href="#AOP的应用场景">☀</a>AOP的应用场景</h3><ul><li>日志管理</li><li>权限认证</li><li>安全检查</li><li>事务控制</li></ul><h2 id="2-Spring-AOP的简单配置"><a class="header-anchor" href="#2-Spring-AOP的简单配置">☀</a>2.Spring AOP的简单配置</h2><p>​ 在上述代码中我们是通过动态代理的方式实现日志功能的，但是比较麻烦，现在我们将要使用spring aop的功能实现此需求，其实通俗点说的话，就是把LogUtil的工具类换成另外一种实现方式。</p><h3 id="1、添加pom依赖"><a class="header-anchor" href="#1、添加pom依赖">☀</a>1、添加pom依赖</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- https://mvnrepository.com/artifact/cglib/cglib --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>cglib<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>cglib<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.3.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.aspectj<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>aspectjweaver<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.9.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- https://mvnrepository.com/artifact/aopalliance/aopalliance --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>aopalliance<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>aopalliance<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-aspects<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>5.2.3.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="2、编写配置"><a class="header-anchor" href="#2、编写配置">☀</a>2、编写配置</h3><ul><li><p>将目标类和切面类加入到IOC容器中，在对应的类上添加组件注解</p><ul><li><p>给LogUtil添加@Component注解</p></li><li><p>给MyCalculator添加@Service注解</p></li><li><p>添加自动扫描的配置</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--别忘了添加context命名空间--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;com.mashibing&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ul></li><li><p>设置程序中的切面类</p><ul><li>在LogUtil.java中添加@Aspect注解</li></ul></li><li><p>设置切面类中的方法是什么时候在哪里执行</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.util;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.annotation.*;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Method;</span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogUtil</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">    设置下面方法在什么时候运行</span></span><br><span class="line"><span class="comment">        @Before:在目标方法之前运行：前置通知</span></span><br><span class="line"><span class="comment">        @After:在目标方法之后运行：后置通知</span></span><br><span class="line"><span class="comment">        @AfterReturning:在目标方法正常返回之后：返回通知</span></span><br><span class="line"><span class="comment">        @AfterThrowing:在目标方法抛出异常后开始运行：异常通知</span></span><br><span class="line"><span class="comment">        @Around:环绕：环绕通知</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">        当编写完注解之后还需要设置在哪些方法上执行，使用表达式</span></span><br><span class="line"><span class="comment">        execution(访问修饰符  返回值类型 方法全称)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Before(&quot;execution( public int com.mashibing.inter.MyCalculator.*(int,int))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">start</span><span class="params">()</span>&#123;</span><br><span class="line"><span class="comment">//        System.out.println(&quot;XXX方法开始执行，使用的参数是：&quot;+ Arrays.asList(objects));</span></span><br><span class="line"><span class="comment">//        System.out.println(method.getName()+&quot;方法开始执行，参数是：&quot;+ Arrays.asList(objects));</span></span><br><span class="line">        System.out.println(<span class="string">&quot;方法开始执行，参数是：&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterReturning(&quot;execution( public int com.mashibing.inter.MyCalculator.*(int,int))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">stop</span><span class="params">()</span>&#123;</span><br><span class="line"><span class="comment">//        System.out.println(&quot;XXX方法执行结束，结果是：&quot;+ Arrays.asList(objects));</span></span><br><span class="line"><span class="comment">//        System.out.println(method.getName()+&quot;方法执行结束，结果是：&quot;+ Arrays.asList(objects));</span></span><br><span class="line">        System.out.println(<span class="string">&quot;方法执行完成，结果是：&quot;</span>);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterThrowing(&quot;execution( public int com.mashibing.inter.MyCalculator.*(int,int))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">logException</span><span class="params">()</span>&#123;</span><br><span class="line"><span class="comment">//        System.out.println(method.getName()+&quot;方法出现异常：&quot;+ e.getMessage());</span></span><br><span class="line">        System.out.println(<span class="string">&quot;方法出现异常：&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@After(&quot;execution( public int com.mashibing.inter.MyCalculator.*(int,int))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">end</span><span class="params">()</span>&#123;</span><br><span class="line"><span class="comment">//        System.out.println(method.getName()+&quot;方法执行结束了......&quot;);</span></span><br><span class="line">        System.out.println(<span class="string">&quot;方法执行结束了......&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>开启基于注解的aop的功能</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.springframework.org/schema/beans&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:context</span>=<span class="string">&quot;http://www.springframework.org/schema/context&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:aop</span>=<span class="string">&quot;http://www.springframework.org/schema/aop&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://www.springframework.org/schema/beans</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/beans/spring-beans.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/context</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/context/spring-context.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/aop</span></span></span><br><span class="line"><span class="string"><span class="tag">       https://www.springframework.org/schema/aop/spring-aop.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;com.mashibing&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">aop:aspectj-autoproxy</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:aspectj-autoproxy</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ul><h3 id="3、测试"><a class="header-anchor" href="#3、测试">☀</a>3、测试</h3><p>MyTest.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">  <span class="keyword">import</span> com.mashibing.inter.Calculator;</span><br><span class="line">  <span class="keyword">import</span> org.springframework.context.ApplicationContext;</span><br><span class="line">  <span class="keyword">import</span> org.springframework.context.support.ClassPathXmlApplicationContext;</span><br><span class="line">  <span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyTest</span> &#123;</span><br><span class="line">      <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span>&#123;</span><br><span class="line">          <span class="type">ApplicationContext</span> <span class="variable">context</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;aop.xml&quot;</span>);</span><br><span class="line">          <span class="type">Calculator</span> <span class="variable">bean</span> <span class="operator">=</span> context.getBean(Calculator.class);</span><br><span class="line">          bean.add(<span class="number">1</span>,<span class="number">1</span>);</span><br><span class="line">      &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>​ spring AOP的动态代理方式是jdk自带的方式，容器中保存的组件是代理对象com.sun.proxy.$Proxy对象</p><h3 id="4、通过cglib来创建代理对象"><a class="header-anchor" href="#4、通过cglib来创建代理对象">☀</a>4、通过cglib来创建代理对象</h3><p>MyCalculator.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.inter;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyCalculator</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">add</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i + j;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">sub</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i - j;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">mult</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i * j;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">div</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i / j;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>MyTest.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyTest</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span>&#123;</span><br><span class="line">        <span class="type">ApplicationContext</span> <span class="variable">context</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;aop.xml&quot;</span>);</span><br><span class="line">        <span class="type">MyCalculator</span> <span class="variable">bean</span> <span class="operator">=</span> context.getBean(MyCalculator.class);</span><br><span class="line">        bean.add(<span class="number">1</span>,<span class="number">1</span>);</span><br><span class="line">        System.out.println(bean);</span><br><span class="line">        System.out.println(bean.getClass());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>​ 可以通过cglib的方式来创建代理对象，此时不需要实现任何接口，代理对象是</p><p>class com.mashibing.inter.MyCalculator$$EnhancerBySpringCGLIB$$1f93b605类型</p><p>​ <strong>综上所述：在spring容器中，如果有接口，那么会使用jdk自带的动态代理，如果没有接口，那么会使用cglib的动态代理。动态代理的实现原理，后续会详细讲。</strong></p><h3 id="注意点："><a class="header-anchor" href="#注意点：">☀</a>注意点：</h3><h4 id="1、切入点表达式"><a class="header-anchor" href="#1、切入点表达式">☀</a>1、切入点表达式</h4><p>​ 在使用表达式的时候，除了之前的写法之外，还可以使用通配符的方式：</p><p>​ *：</p><p>​ 1、匹配一个或者多个字符</p><p>​ execution( public int <a target="_blank" rel="noopener external nofollow noreferrer" href="http://com.mashibing.inter.My">com.mashibing.inter.My</a>*alculator.*(int,int))</p><p>​ 2、匹配任意一个参数，</p><p>​ execution( public int com.mashibing.inter.MyCalculator.*(int,*))</p><p>​ 3、只能匹配一层路径，如果项目路径下有多层目录，那么*只能匹配一层路径</p><p>​ 4、权限位置不能使用*，如果想表示全部权限，那么不写即可</p><p>​ execution( * com.mashibing.inter.MyCalculator.*(int,*))</p><p>​ …：</p><p>​ 1、匹配多个参数，任意类型参数</p><p>​ execution( * com.mashibing.inter.MyCalculator.*(…))</p><p>​ 2、匹配任意多层路径</p><p>​ execution( * com.mashibing…MyCalculator.*(…))</p><p>​ 在写表达式的时候，可以有N多种写法，但是有一种最偷懒和最精确的方式：</p><p>​ 最偷懒的方式：execution(* *(…)) 或者 execution(* *.*(…))</p><p>​ 最精确的方式：execution( public int com.mashibing.inter.MyCalculator.add(int,int))</p><p>​ 除此之外，在表达式中还支持 &amp;&amp;、||、！的方式</p><p>​ &amp;&amp;：两个表达式同时</p><p>​ execution( public int com.mashibing.inter.MyCalculator.*(…)) &amp;&amp; execution(* *.*(int,int) )</p><p>​ ||：任意满足一个表达式即可</p><p>​ execution( public int com.mashibing.inter.MyCalculator.*(…)) &amp;&amp; execution(* *.*(int,int) )</p><p>​ ！：只要不是这个位置都可以进行切入</p><p>​ &amp;&amp;：两个表达式同时</p><p>​ execution( public int com.mashibing.inter.MyCalculator.*(…))</p><h4 id="2、通知方法的执行顺序"><a class="header-anchor" href="#2、通知方法的执行顺序">☀</a>2、通知方法的执行顺序</h4><p>​ 在之前的代码中大家一直对通知的执行顺序有疑问，其实执行的结果并没有错，大家需要注意：</p><p>​ 1、正常执行：@Before—&gt;@After—&gt;@AfterReturning</p><p>​ 2、异常执行：@Before—&gt;@After—&gt;@AfterThrowing</p><h4 id="3、获取方法的详细信息"><a class="header-anchor" href="#3、获取方法的详细信息">☀</a>3、获取方法的详细信息</h4><p>​ 在上面的案例中，我们并没有获取Method的详细信息，例如方法名、参数列表等信息，想要获取的话其实非常简单，只需要添加JoinPoint参数即可。</p><p>LogUtil.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.util;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.JoinPoint;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.annotation.*;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogUtil</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Before(&quot;execution( public int com.mashibing.inter.MyCalculator.*(int,int))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">start</span><span class="params">(JoinPoint joinPoint)</span>&#123;</span><br><span class="line">        Object[] args = joinPoint.getArgs();</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(name+<span class="string">&quot;方法开始执行，参数是：&quot;</span>+ Arrays.asList(args));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterReturning(&quot;execution( public int com.mashibing.inter.MyCalculator.*(int,int))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">stop</span><span class="params">(JoinPoint joinPoint)</span>&#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(name+<span class="string">&quot;方法执行完成，结果是：&quot;</span>);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterThrowing(&quot;execution( public int com.mashibing.inter.MyCalculator.*(int,int))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">logException</span><span class="params">(JoinPoint joinPoint)</span>&#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(name+<span class="string">&quot;方法出现异常：&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@After(&quot;execution( public int com.mashibing.inter.MyCalculator.*(int,int))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">end</span><span class="params">(JoinPoint joinPoint)</span>&#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(name+<span class="string">&quot;方法执行结束了......&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>​ 刚刚只是获取了方法的信息，但是如果需要获取结果，还需要添加另外一个方法参数，并且告诉spring使用哪个参数来进行结果接收</p><p>LogUtil.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@AfterReturning(value = &quot;execution( public int com.mashibing.inter.MyCalculator.*(int,int))&quot;,returning = &quot;result&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">stop</span><span class="params">(JoinPoint joinPoint,Object result)</span>&#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">    System.out.println(name+<span class="string">&quot;方法执行完成，结果是：&quot;</span>+result);</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>​ 也可以通过相同的方式来获取异常的信息</p><p>LogUtil.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@AfterThrowing(value = &quot;execution( public int com.mashibing.inter.MyCalculator.*(int,int))&quot;,throwing = &quot;exception&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">logException</span><span class="params">(JoinPoint joinPoint,Exception exception)</span>&#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">    System.out.println(name+<span class="string">&quot;方法出现异常：&quot;</span>+exception);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="4、spring对通过方法的要求"><a class="header-anchor" href="#4、spring对通过方法的要求">☀</a>4、spring对通过方法的要求</h4><p>​ spring对于通知方法的要求并不是很高，你可以任意改变方法的返回值和方法的访问修饰符，但是唯一不能修改的就是方法的参数，会出现参数绑定的错误，原因在于通知方法是spring利用反射调用的，每次方法调用得确定这个方法的参数的值。</p><p>LogUtil.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">    <span class="meta">@After(&quot;execution( public int com.mashibing.inter.MyCalculator.*(int,int))&quot;)</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="title function_">end</span><span class="params">(JoinPoint joinPoint,String aa)</span>&#123;</span><br><span class="line"><span class="comment">//        System.out.println(method.getName()+&quot;方法执行结束了......&quot;);</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(name+<span class="string">&quot;方法执行结束了......&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><h4 id="5、表达式的抽取"><a class="header-anchor" href="#5、表达式的抽取">☀</a>5、表达式的抽取</h4><p>如果在实际使用过程中，多个方法的表达式是一致的话，那么可以考虑将切入点表达式抽取出来：</p><p>​ a、随便生命一个没有实现的返回void的空方法</p><p>​ b、给方法上标注@Potintcut注解</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.util;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.JoinPoint;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.annotation.*;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogUtil</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Pointcut(&quot;execution( public int com.mashibing.inter.MyCalculator.*(int,int))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">myPoint</span><span class="params">()</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Before(&quot;myPoint()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">start</span><span class="params">(JoinPoint joinPoint)</span>&#123;</span><br><span class="line">        Object[] args = joinPoint.getArgs();</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(name+<span class="string">&quot;方法开始执行，参数是：&quot;</span>+ Arrays.asList(args));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterReturning(value = &quot;myPoint()&quot;,returning = &quot;result&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">stop</span><span class="params">(JoinPoint joinPoint,Object result)</span>&#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(name+<span class="string">&quot;方法执行完成，结果是：&quot;</span>+result);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterThrowing(value = &quot;myPoint()&quot;,throwing = &quot;exception&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">logException</span><span class="params">(JoinPoint joinPoint,Exception exception)</span>&#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(name+<span class="string">&quot;方法出现异常：&quot;</span>+exception.getMessage());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@After(&quot;myPoint()&quot;)</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="title function_">end</span><span class="params">(JoinPoint joinPoint)</span>&#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(name+<span class="string">&quot;方法执行结束了......&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="6、环绕通知的使用"><a class="header-anchor" href="#6、环绕通知的使用">☀</a>6、环绕通知的使用</h4><p>LogUtil.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.util;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.JoinPoint;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.ProceedingJoinPoint;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.annotation.*;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogUtil</span> &#123;</span><br><span class="line">    <span class="meta">@Pointcut(&quot;execution( public int com.mashibing.inter.MyCalculator.*(int,int))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">myPoint</span><span class="params">()</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 环绕通知是spring中功能最强大的通知</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> proceedingJoinPoint</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Around(&quot;myPoint()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">myAround</span><span class="params">(ProceedingJoinPoint proceedingJoinPoint)</span>&#123;</span><br><span class="line">        Object[] args = proceedingJoinPoint.getArgs();</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> proceedingJoinPoint.getSignature().getName();</span><br><span class="line">        <span class="type">Object</span> <span class="variable">proceed</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕前置通知:&quot;</span>+name+<span class="string">&quot;方法开始，参数是&quot;</span>+Arrays.asList(args));</span><br><span class="line">            <span class="comment">//利用反射调用目标方法，就是method.invoke()</span></span><br><span class="line">            proceed = proceedingJoinPoint.proceed(args);</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕返回通知:&quot;</span>+name+<span class="string">&quot;方法返回，返回值是&quot;</span>+proceed);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Throwable e) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕异常通知&quot;</span>+name+<span class="string">&quot;方法出现异常，异常信息是：&quot;</span>+e);</span><br><span class="line">        &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕后置通知&quot;</span>+name+<span class="string">&quot;方法结束&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> proceed;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>​ 总结：环绕通知的执行顺序是优于普通通知的，具体的执行顺序如下：</p><p>环绕前置–&gt;普通前置–&gt;目标方法执行–&gt;环绕正常结束/出现异常–&gt;环绕后置–&gt;普通后置–&gt;普通返回或者异常。</p><p>但是需要注意的是，如果出现了异常，那么环绕通知会处理或者捕获异常，普通异常通知是接收不到的，因此最好的方式是在环绕异常通知中向外抛出异常。</p><h4 id="7、多切面运行的顺序"><a class="header-anchor" href="#7、多切面运行的顺序">☀</a>7、多切面运行的顺序</h4><p>​ 如果有多个切面要进行执行，那么顺序是什么样的呢？</p><p>LogUtil.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.util;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.JoinPoint;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.ProceedingJoinPoint;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.annotation.*;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogUtil</span> &#123;</span><br><span class="line">    <span class="meta">@Pointcut(&quot;execution( public int com.mashibing.inter.MyCalculator.*(int,int))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">myPoint</span><span class="params">()</span>&#123;&#125;</span><br><span class="line">    <span class="meta">@Before(&quot;myPoint()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">start</span><span class="params">(JoinPoint joinPoint)</span>&#123;</span><br><span class="line"><span class="comment">//        System.out.println(&quot;XXX方法开始执行，使用的参数是：&quot;+ Arrays.asList(objects));</span></span><br><span class="line"><span class="comment">//        System.out.println(method.getName()+&quot;方法开始执行，参数是：&quot;+ Arrays.asList(objects));</span></span><br><span class="line">        Object[] args = joinPoint.getArgs();</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(<span class="string">&quot;Log:&quot;</span>+name+<span class="string">&quot;方法开始执行，参数是：&quot;</span>+ Arrays.asList(args));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterReturning(value = &quot;myPoint()&quot;,returning = &quot;result&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">stop</span><span class="params">(JoinPoint joinPoint,Object result)</span>&#123;</span><br><span class="line"><span class="comment">//        System.out.println(&quot;XXX方法执行结束，结果是：&quot;+ Arrays.asList(objects));</span></span><br><span class="line"><span class="comment">//        System.out.println(method.getName()+&quot;方法执行结束，结果是：&quot;+ Arrays.asList(objects));</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(<span class="string">&quot;Log:&quot;</span>+name+<span class="string">&quot;方法执行完成，结果是：&quot;</span>+result);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterThrowing(value = &quot;myPoint()&quot;,throwing = &quot;exception&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">logException</span><span class="params">(JoinPoint joinPoint,Exception exception)</span>&#123;</span><br><span class="line"><span class="comment">//        System.out.println(method.getName()+&quot;方法出现异常：&quot;+ e.getMessage());</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(<span class="string">&quot;Log:&quot;</span>+name+<span class="string">&quot;方法出现异常：&quot;</span>+exception.getMessage());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@After(&quot;myPoint()&quot;)</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="title function_">end</span><span class="params">(JoinPoint joinPoint)</span>&#123;</span><br><span class="line"><span class="comment">//        System.out.println(method.getName()+&quot;方法执行结束了......&quot;);</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(<span class="string">&quot;Log:&quot;</span>+name+<span class="string">&quot;方法执行结束了......&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 环绕通知是spring中功能最强大的通知</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> proceedingJoinPoint</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="comment">//@Around(&quot;myPoint()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">myAround</span><span class="params">(ProceedingJoinPoint proceedingJoinPoint)</span>&#123;</span><br><span class="line">        Object[] args = proceedingJoinPoint.getArgs();</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> proceedingJoinPoint.getSignature().getName();</span><br><span class="line">        <span class="type">Object</span> <span class="variable">proceed</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕前置通知:&quot;</span>+name+<span class="string">&quot;方法开始，参数是&quot;</span>+Arrays.asList(args));</span><br><span class="line">            <span class="comment">//利用反射调用目标方法，就是method.invoke()</span></span><br><span class="line">            proceed = proceedingJoinPoint.proceed(args);</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕返回通知:&quot;</span>+name+<span class="string">&quot;方法返回，返回值是&quot;</span>+proceed);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Throwable e) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕异常通知&quot;</span>+name+<span class="string">&quot;方法出现异常，异常信息是：&quot;</span>+e);</span><br><span class="line">        &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕后置通知&quot;</span>+name+<span class="string">&quot;方法结束&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> proceed;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>SecurityAspect.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.util;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.JoinPoint;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.ProceedingJoinPoint;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.annotation.*;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SecurityAspect</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Before(&quot;com.mashibing.util.LogUtil.myPoint()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">start</span><span class="params">(JoinPoint joinPoint)</span>&#123;</span><br><span class="line">        Object[] args = joinPoint.getArgs();</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(<span class="string">&quot;Security:&quot;</span>+name+<span class="string">&quot;方法开始执行，参数是：&quot;</span>+ Arrays.asList(args));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterReturning(value = &quot;com.mashibing.util.LogUtil.myPoint()&quot;,returning = &quot;result&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">stop</span><span class="params">(JoinPoint joinPoint,Object result)</span>&#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(<span class="string">&quot;Security:&quot;</span>+name+<span class="string">&quot;方法执行完成，结果是：&quot;</span>+result);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterThrowing(value = &quot;com.mashibing.util.LogUtil.myPoint()&quot;,throwing = &quot;exception&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">logException</span><span class="params">(JoinPoint joinPoint,Exception exception)</span>&#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(<span class="string">&quot;Security:&quot;</span>+name+<span class="string">&quot;方法出现异常：&quot;</span>+exception.getMessage());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@After(&quot;com.mashibing.util.LogUtil.myPoint()&quot;)</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="title function_">end</span><span class="params">(JoinPoint joinPoint)</span>&#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(<span class="string">&quot;Security:&quot;</span>+name+<span class="string">&quot;方法执行结束了......&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 环绕通知是spring中功能最强大的通知</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> proceedingJoinPoint</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="comment">//@Around(&quot;myPoint()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">myAround</span><span class="params">(ProceedingJoinPoint proceedingJoinPoint)</span>&#123;</span><br><span class="line">        Object[] args = proceedingJoinPoint.getArgs();</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> proceedingJoinPoint.getSignature().getName();</span><br><span class="line">        <span class="type">Object</span> <span class="variable">proceed</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕前置通知:&quot;</span>+name+<span class="string">&quot;方法开始，参数是&quot;</span>+Arrays.asList(args));</span><br><span class="line">            <span class="comment">//利用反射调用目标方法，就是method.invoke()</span></span><br><span class="line">            proceed = proceedingJoinPoint.proceed(args);</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕返回通知:&quot;</span>+name+<span class="string">&quot;方法返回，返回值是&quot;</span>+proceed);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Throwable e) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕异常通知&quot;</span>+name+<span class="string">&quot;方法出现异常，异常信息是：&quot;</span>+e);</span><br><span class="line">        &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕后置通知&quot;</span>+name+<span class="string">&quot;方法结束&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> proceed;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>​ 在spring中，默认是按照切面名称的字典顺序进行执行的，但是如果想自己改变具体的执行顺序的话，可以使用@Order注解来解决，数值越小，优先级越高。</p><p>LogUtil.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.util;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.JoinPoint;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.ProceedingJoinPoint;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.annotation.*;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="meta">@Order(2)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogUtil</span> &#123;</span><br><span class="line">    <span class="meta">@Pointcut(&quot;execution( public int com.mashibing.inter.MyCalculator.*(int,int))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">myPoint</span><span class="params">()</span>&#123;&#125;</span><br><span class="line">    <span class="meta">@Before(&quot;myPoint()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">start</span><span class="params">(JoinPoint joinPoint)</span>&#123;</span><br><span class="line"><span class="comment">//        System.out.println(&quot;XXX方法开始执行，使用的参数是：&quot;+ Arrays.asList(objects));</span></span><br><span class="line"><span class="comment">//        System.out.println(method.getName()+&quot;方法开始执行，参数是：&quot;+ Arrays.asList(objects));</span></span><br><span class="line">        Object[] args = joinPoint.getArgs();</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(<span class="string">&quot;Log:&quot;</span>+name+<span class="string">&quot;方法开始执行，参数是：&quot;</span>+ Arrays.asList(args));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterReturning(value = &quot;myPoint()&quot;,returning = &quot;result&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">stop</span><span class="params">(JoinPoint joinPoint,Object result)</span>&#123;</span><br><span class="line"><span class="comment">//        System.out.println(&quot;XXX方法执行结束，结果是：&quot;+ Arrays.asList(objects));</span></span><br><span class="line"><span class="comment">//        System.out.println(method.getName()+&quot;方法执行结束，结果是：&quot;+ Arrays.asList(objects));</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(<span class="string">&quot;Log:&quot;</span>+name+<span class="string">&quot;方法执行完成，结果是：&quot;</span>+result);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterThrowing(value = &quot;myPoint()&quot;,throwing = &quot;exception&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">logException</span><span class="params">(JoinPoint joinPoint,Exception exception)</span>&#123;</span><br><span class="line"><span class="comment">//        System.out.println(method.getName()+&quot;方法出现异常：&quot;+ e.getMessage());</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(<span class="string">&quot;Log:&quot;</span>+name+<span class="string">&quot;方法出现异常：&quot;</span>+exception.getMessage());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@After(&quot;myPoint()&quot;)</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="title function_">end</span><span class="params">(JoinPoint joinPoint)</span>&#123;</span><br><span class="line"><span class="comment">//        System.out.println(method.getName()+&quot;方法执行结束了......&quot;);</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(<span class="string">&quot;Log:&quot;</span>+name+<span class="string">&quot;方法执行结束了......&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 环绕通知是spring中功能最强大的通知</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> proceedingJoinPoint</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="comment">//@Around(&quot;myPoint()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">myAround</span><span class="params">(ProceedingJoinPoint proceedingJoinPoint)</span>&#123;</span><br><span class="line">        Object[] args = proceedingJoinPoint.getArgs();</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> proceedingJoinPoint.getSignature().getName();</span><br><span class="line">        <span class="type">Object</span> <span class="variable">proceed</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕前置通知:&quot;</span>+name+<span class="string">&quot;方法开始，参数是&quot;</span>+Arrays.asList(args));</span><br><span class="line">            <span class="comment">//利用反射调用目标方法，就是method.invoke()</span></span><br><span class="line">            proceed = proceedingJoinPoint.proceed(args);</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕返回通知:&quot;</span>+name+<span class="string">&quot;方法返回，返回值是&quot;</span>+proceed);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Throwable e) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕异常通知&quot;</span>+name+<span class="string">&quot;方法出现异常，异常信息是：&quot;</span>+e);</span><br><span class="line">        &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕后置通知&quot;</span>+name+<span class="string">&quot;方法结束&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> proceed;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>SecurityAspect.java</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.mashibing.util;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.JoinPoint;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.ProceedingJoinPoint;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.annotation.*;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="meta">@Order(1)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SecurityAspect</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Before(&quot;com.mashibing.util.LogUtil.myPoint()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">start</span><span class="params">(JoinPoint joinPoint)</span>&#123;</span><br><span class="line">        Object[] args = joinPoint.getArgs();</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(<span class="string">&quot;Security:&quot;</span>+name+<span class="string">&quot;方法开始执行，参数是：&quot;</span>+ Arrays.asList(args));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterReturning(value = &quot;com.mashibing.util.LogUtil.myPoint()&quot;,returning = &quot;result&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">stop</span><span class="params">(JoinPoint joinPoint,Object result)</span>&#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(<span class="string">&quot;Security:&quot;</span>+name+<span class="string">&quot;方法执行完成，结果是：&quot;</span>+result);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterThrowing(value = &quot;com.mashibing.util.LogUtil.myPoint()&quot;,throwing = &quot;exception&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">logException</span><span class="params">(JoinPoint joinPoint,Exception exception)</span>&#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(<span class="string">&quot;Security:&quot;</span>+name+<span class="string">&quot;方法出现异常：&quot;</span>+exception.getMessage());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@After(&quot;com.mashibing.util.LogUtil.myPoint()&quot;)</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="title function_">end</span><span class="params">(JoinPoint joinPoint)</span>&#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        System.out.println(<span class="string">&quot;Security:&quot;</span>+name+<span class="string">&quot;方法执行结束了......&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 环绕通知是spring中功能最强大的通知</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> proceedingJoinPoint</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="comment">//@Around(&quot;myPoint()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">myAround</span><span class="params">(ProceedingJoinPoint proceedingJoinPoint)</span>&#123;</span><br><span class="line">        Object[] args = proceedingJoinPoint.getArgs();</span><br><span class="line">        <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> proceedingJoinPoint.getSignature().getName();</span><br><span class="line">        <span class="type">Object</span> <span class="variable">proceed</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕前置通知:&quot;</span>+name+<span class="string">&quot;方法开始，参数是&quot;</span>+Arrays.asList(args));</span><br><span class="line">            <span class="comment">//利用反射调用目标方法，就是method.invoke()</span></span><br><span class="line">            proceed = proceedingJoinPoint.proceed(args);</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕返回通知:&quot;</span>+name+<span class="string">&quot;方法返回，返回值是&quot;</span>+proceed);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Throwable e) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕异常通知&quot;</span>+name+<span class="string">&quot;方法出现异常，异常信息是：&quot;</span>+e);</span><br><span class="line">        &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;环绕后置通知&quot;</span>+name+<span class="string">&quot;方法结束&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> proceed;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>​ 如果需要添加环绕通知呢，具体的执行顺序又会是什么顺序呢？</p><p>​ 因为环绕通知在进行添加的时候，是在切面层引入的，所以在哪个切面添加环绕通知，那么就会在哪个切面执行。</p><h2 id="3-基于配置的AOP配置"><a class="header-anchor" href="#3-基于配置的AOP配置">☀</a>3.基于配置的AOP配置</h2><p>​ 之前我们讲解了基于注解的AOP配置方式，下面我们开始讲一下基于xml的配置方式，虽然在现在的企业级开发中使用注解的方式比较多，但是你不能不会，因此需要简单的进行配置，注解配置快速简单，配置的方式共呢个完善。</p><p>1、将所有的注解都进行删除</p><p>2、添加配置文件</p><p>aop.xml</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.springframework.org/schema/beans&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:context</span>=<span class="string">&quot;http://www.springframework.org/schema/context&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:aop</span>=<span class="string">&quot;http://www.springframework.org/schema/aop&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://www.springframework.org/schema/beans</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/beans/spring-beans.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/context</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/context/spring-context.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/aop</span></span></span><br><span class="line"><span class="string"><span class="tag">       https://www.springframework.org/schema/aop/spring-aop.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;com.mashibing&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">aop:aspectj-autoproxy</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:aspectj-autoproxy</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;logUtil&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.mashibing.util.LogUtil2&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;securityAspect&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.mashibing.util.SecurityAspect&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;myCalculator&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.mashibing.inter.MyCalculator&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">aop:config</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">aop:pointcut</span> <span class="attr">id</span>=<span class="string">&quot;globalPoint&quot;</span> <span class="attr">expression</span>=<span class="string">&quot;execution(public int com.mashibing.inter.MyCalculator.*(int,int))&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">aop:aspect</span> <span class="attr">ref</span>=<span class="string">&quot;logUtil&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:pointcut</span> <span class="attr">id</span>=<span class="string">&quot;mypoint&quot;</span> <span class="attr">expression</span>=<span class="string">&quot;execution(public int com.mashibing.inter.MyCalculator.*(int,int))&quot;</span>/&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:before</span> <span class="attr">method</span>=<span class="string">&quot;start&quot;</span> <span class="attr">pointcut-ref</span>=<span class="string">&quot;mypoint&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:before</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:after</span> <span class="attr">method</span>=<span class="string">&quot;end&quot;</span> <span class="attr">pointcut-ref</span>=<span class="string">&quot;mypoint&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:after</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:after-returning</span> <span class="attr">method</span>=<span class="string">&quot;stop&quot;</span> <span class="attr">pointcut-ref</span>=<span class="string">&quot;mypoint&quot;</span> <span class="attr">returning</span>=<span class="string">&quot;result&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:after-returning</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:after-throwing</span> <span class="attr">method</span>=<span class="string">&quot;logException&quot;</span> <span class="attr">pointcut-ref</span>=<span class="string">&quot;mypoint&quot;</span> <span class="attr">throwing</span>=<span class="string">&quot;exception&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:after-throwing</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:around</span> <span class="attr">method</span>=<span class="string">&quot;myAround&quot;</span> <span class="attr">pointcut-ref</span>=<span class="string">&quot;mypoint&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:around</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">aop:aspect</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">aop:aspect</span> <span class="attr">ref</span>=<span class="string">&quot;securityAspect&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:before</span> <span class="attr">method</span>=<span class="string">&quot;start&quot;</span> <span class="attr">pointcut-ref</span>=<span class="string">&quot;globalPoint&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:before</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:after</span> <span class="attr">method</span>=<span class="string">&quot;end&quot;</span> <span class="attr">pointcut-ref</span>=<span class="string">&quot;globalPoint&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:after</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:after-returning</span> <span class="attr">method</span>=<span class="string">&quot;stop&quot;</span> <span class="attr">pointcut-ref</span>=<span class="string">&quot;globalPoint&quot;</span> <span class="attr">returning</span>=<span class="string">&quot;result&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:after-returning</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:after-throwing</span> <span class="attr">method</span>=<span class="string">&quot;logException&quot;</span> <span class="attr">pointcut-ref</span>=<span class="string">&quot;globalPoint&quot;</span> <span class="attr">throwing</span>=<span class="string">&quot;exception&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:after-throwing</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:around</span> <span class="attr">method</span>=<span class="string">&quot;myAround&quot;</span> <span class="attr">pointcut-ref</span>=<span class="string">&quot;mypoint&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:around</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">aop:aspect</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">aop:config</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure><div class="footer"><div class="copyright"><blockquote><p>博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议</p><p>本文永久链接是：<a href="http://aner1001.gitee.io/posts/2021/02/25/d257d0f10a3c/">http://aner1001.gitee.io/posts/2021/02/25/d257d0f10a3c/</a></p></blockquote></div></div><div class="article-meta" id="bottom"><div class="new-meta-box"><div class="new-meta-item date" itemprop="dateUpdated" datetime="2021-02-25T17:22:19+08:00"><a class="notlink"><i class="fas fa-edit fa-fw" aria-hidden="true"></i><p>更新于：2021年2月25日</p></a></div><div class="new-meta-item meta-tags"><a class="tag" href="/tags/Spring/" rel="nofollow"><i class="fas fa-hashtag fa-fw" aria-hidden="true"></i><p>Spring</p></a></div><div class="new-meta-item share -mob-share-list"><div class="-mob-share-list share-body"> <a class="-mob-share-qq" title="" rel="external nofollow noopener noreferrer noopener" target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=http://aner1001.gitee.io/posts/2021/02/25/d257d0f10a3c/&title=Spring学习笔记-AOP基本介绍 - Tang's blog.&summary=AOP：Aspect Oriented Programming  面向切面编程
OOP：Object Oriented Programming  面向对象编程"><img src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/qq.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/qq.png" srcset=""></a> <a class="-mob-share-qzone" title="" rel="external nofollow noopener noreferrer noopener" target="_blank" href="https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=http://aner1001.gitee.io/posts/2021/02/25/d257d0f10a3c/&title=Spring学习笔记-AOP基本介绍 - Tang's blog.&summary=AOP：Aspect Oriented Programming  面向切面编程
OOP：Object Oriented Programming  面向对象编程"><img src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/qzone.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/qzone.png" srcset=""></a> <a class="-mob-share-weibo" title="" rel="external nofollow noopener noreferrer noopener" target="_blank" href="http://service.weibo.com/share/share.php?url=http://aner1001.gitee.io/posts/2021/02/25/d257d0f10a3c/&title=Spring学习笔记-AOP基本介绍 - Tang's blog.&summary=AOP：Aspect Oriented Programming  面向切面编程
OOP：Object Oriented Programming  面向对象编程"><img src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/weibo.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/weibo.png" srcset=""></a><div class="hoverbox"> <a class="share"><img src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/wechat.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/wechat.png" srcset=""></a><div class="target"> <img src=""></div></div> <a class="-mob-share-telegram" title="" rel="external nofollow noopener noreferrer noopener" target="_blank" href="https://t.me/share/url?url=http://aner1001.gitee.io/posts/2021/02/25/d257d0f10a3c/&text=Spring学习笔记-AOP基本介绍 - Tang's blog."><img src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/telegram.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/telegram.png" srcset=""></a></div></div></div></div><div class="prev-next"><a class="prev" href="/posts/2021/02/25/e67109eb06c2/"><p class="title"><i class="fas fa-chevron-left" aria-hidden="true"></i>SpringMVC学习笔记1-介绍和使用</p><p class="content">MVC是模型(Model)、视图(View)、控制器(Controller)的简写，是一种软件设计规范。就是将业务逻辑、数据、显示分离的方法来组织代码。MVC主要作用是降低了视图与业务逻辑间的双...</p></a><a class="next" href="/posts/2021/02/25/024c1ad1f288/"><p class="title">Spring学习笔记-IOC注解<i class="fas fa-chevron-right" aria-hidden="true"></i></p><p class="content">我们都是通过xml文件进行bean或者某些属性的赋值，其实还有另外一种注解的方式，在企业开发中使用的很多，在bean上添加注解，可以快速的将bean注册到ioc容器。 ☀1.使用注解的方式注册...</p></a></div></article><article class="post white-box reveal shadow" id="comments"><p ct><i class="fas fa-comments"></i> 评论</p><div id="valine_container" class="valine_thread"><i class="fas fa-cog fa-spin fa-fw fa-2x"></i></div></article></div><aside class="l_side"><section class="widget list group shadow desktop mobile"><header><a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/spring-projects/spring-framework"><i class="fab fa-github fa-fw" aria-hidden="true"></i> <span class="name">Spring</span></a></header><div class="content"><ul class="list entry navigation"><li><a class="flat-box" title="/posts/2021/02/25/426fd5e7199b/" href="/posts/2021/02/25/426fd5e7199b/" id="posts20210225426fd5e7199b"><div class="name"> Spring学习笔记-基本介绍</div></a></li><li><a class="flat-box" title="/posts/2021/02/25/9cb0a8c2857f/" href="/posts/2021/02/25/9cb0a8c2857f/" id="posts202102259cb0a8c2857f"><div class="name"> Spring学习笔记-IOC配置</div></a></li><li><a class="flat-box" title="/posts/2021/02/25/024c1ad1f288/" href="/posts/2021/02/25/024c1ad1f288/" id="posts20210225024c1ad1f288"><div class="name"> Spring学习笔记-IOC注解</div></a></li><li><a class="flat-box" title="/posts/2021/02/25/d257d0f10a3c/" href="/posts/2021/02/25/d257d0f10a3c/" id="posts20210225d257d0f10a3c"><div class="name"> Spring学习笔记-AOP基本介绍</div></a></li></ul></div></section><section class="widget toc-wrapper shadow desktop mobile" id="toc-div"><header><i class="fas fa-list fa-fw" aria-hidden="true"></i> <span class="name">本文目录</span></header><div class="content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-AOP%E7%9A%84%E6%A6%82%E5%BF%B5"><span class="toc-text">1.AOP的概念</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E5%BC%95%E5%85%A5AOP"><span class="toc-text">为什么要引入AOP?</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#AOP%E7%9A%84%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5%E5%8F%8A%E6%9C%AF%E8%AF%AD"><span class="toc-text">AOP的核心概念及术语</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#AOP%E7%9A%84%E9%80%9A%E7%9F%A5%E7%B1%BB%E5%9E%8B"><span class="toc-text">AOP的通知类型</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#AOP%E7%9A%84%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF"><span class="toc-text">AOP的应用场景</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-Spring-AOP%E7%9A%84%E7%AE%80%E5%8D%95%E9%85%8D%E7%BD%AE"><span class="toc-text">2.Spring AOP的简单配置</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1%E3%80%81%E6%B7%BB%E5%8A%A0pom%E4%BE%9D%E8%B5%96"><span class="toc-text">1、添加pom依赖</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2%E3%80%81%E7%BC%96%E5%86%99%E9%85%8D%E7%BD%AE"><span class="toc-text">2、编写配置</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3%E3%80%81%E6%B5%8B%E8%AF%95"><span class="toc-text">3、测试</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4%E3%80%81%E9%80%9A%E8%BF%87cglib%E6%9D%A5%E5%88%9B%E5%BB%BA%E4%BB%A3%E7%90%86%E5%AF%B9%E8%B1%A1"><span class="toc-text">4、通过cglib来创建代理对象</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B3%A8%E6%84%8F%E7%82%B9%EF%BC%9A"><span class="toc-text">注意点：</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1%E3%80%81%E5%88%87%E5%85%A5%E7%82%B9%E8%A1%A8%E8%BE%BE%E5%BC%8F"><span class="toc-text">1、切入点表达式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2%E3%80%81%E9%80%9A%E7%9F%A5%E6%96%B9%E6%B3%95%E7%9A%84%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F"><span class="toc-text">2、通知方法的执行顺序</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3%E3%80%81%E8%8E%B7%E5%8F%96%E6%96%B9%E6%B3%95%E7%9A%84%E8%AF%A6%E7%BB%86%E4%BF%A1%E6%81%AF"><span class="toc-text">3、获取方法的详细信息</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4%E3%80%81spring%E5%AF%B9%E9%80%9A%E8%BF%87%E6%96%B9%E6%B3%95%E7%9A%84%E8%A6%81%E6%B1%82"><span class="toc-text">4、spring对通过方法的要求</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5%E3%80%81%E8%A1%A8%E8%BE%BE%E5%BC%8F%E7%9A%84%E6%8A%BD%E5%8F%96"><span class="toc-text">5、表达式的抽取</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#6%E3%80%81%E7%8E%AF%E7%BB%95%E9%80%9A%E7%9F%A5%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="toc-text">6、环绕通知的使用</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#7%E3%80%81%E5%A4%9A%E5%88%87%E9%9D%A2%E8%BF%90%E8%A1%8C%E7%9A%84%E9%A1%BA%E5%BA%8F"><span class="toc-text">7、多切面运行的顺序</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-%E5%9F%BA%E4%BA%8E%E9%85%8D%E7%BD%AE%E7%9A%84AOP%E9%85%8D%E7%BD%AE"><span class="toc-text">3.基于配置的AOP配置</span></a></li></ol></div></section></aside><script>window.pdata={},pdata.ispage=!0,pdata.postTitle="Spring学习笔记-AOP基本介绍",pdata.commentPath="",pdata.commentPlaceholder="";var l_header=document.getElementById("l_header");l_header.classList.add("show");var cover_wrapper=document.querySelector(".cover-wrapper");cover_wrapper.id="none",cover_wrapper.style.display="none"</script></div><footer class="footer clearfix"><br><br><div class="aplayer-container"><meting-js theme="#1BCDFC" autoplay="false" volume="0.7" loop="all" order="list" fixed="false" list-max-height="320px" server="netease" type="playlist" id="5472211102" list-folded="true"></meting-js></div><br><div class="social-wrapper"><a href="/atom.xml" class="social fas fa-rss flat-btn" target="_blank" rel="external nofollow noopener noreferrer"></a><a href="mailto:584856024@qq.com" class="social fas fa-envelope flat-btn" target="_blank" rel="external nofollow noopener noreferrer"></a><a href="https://github.com/aner1001" class="social fab fa-github flat-btn" target="_blank" rel="external nofollow noopener noreferrer"></a><a href="https://music.163.com/#/user/home?id=1402271985" class="social fas fa-headphones-alt flat-btn" target="_blank" rel="external nofollow noopener noreferrer"></a></div><div><p>博客内容遵循 <a target="_blank" rel="noopener external nofollow noreferrer" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh">署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议</a></p></div><div><p><span id="lc-sv">本站总访问量为<span id="number"><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span> 次</span> <span id="lc-uv">访客数为<span id="number"><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span> 人</span></p></div> 本站使用 <a href="https://github.com/volantis-x/hexo-theme-volantis/tree/4.3.1" rel="external nofollow noreferrer" target="_blank" class="codename">Volantis</a> 作为主题，总访问量为<span id="busuanzi_value_site_pv"><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span> 次<div class="copyright"><p><a href="/">Copyright © 2021-2021 XXX</a></p></div></footer><a id="s-top" class="fas fa-arrow-up fa-fw" href="javascript:void(0)" rel="external nofollow noreferrer"></a></div></div><div><script>function VPjax(){function e(e,t){this.name=t||e.name,this.run=()=>{e()}}this.list=[],this.start=()=>{for(var e=0;e<this.list.length;e++)this.list[e].run()},this.push=(t,n)=>{var i=new e(t,n);this.list.push(i)}}function loadScript(e,t){setTimeout((function(){var n=document.getElementsByTagName("head")[0]||document.documentElement,i=document.createElement("script");i.setAttribute("type","text/javascript"),t&&(i.onload=t),i.setAttribute("src",e),n.appendChild(i)}))}window.volantis={},window.volantis.loadcss=document.getElementById("loadcss"),volantis.pjax={},volantis.pjax.method={complete:new VPjax,error:new VPjax,send:new VPjax},volantis.pjax={...volantis.pjax,push:volantis.pjax.method.complete.push,error:volantis.pjax.method.error.push,send:volantis.pjax.method.send.push};var loadCSS=function(e,t,n,i){var o,a=window.document,s=a.createElement("link");if(t)o=t;else{var r=(a.body||a.getElementsByTagName("head")[0]).childNodes;o=r[r.length-1]}var d=a.styleSheets;if(i)for(var l in i)i.hasOwnProperty(l)&&s.setAttribute(l,i[l]);s.rel="stylesheet",s.href=e,s.media="only x",function e(t){if(a.body)return t();setTimeout((function(){e(t)}))}((function(){o.parentNode.insertBefore(s,t?o:o.nextSibling)}));var u=function(e){for(var t=s.href,n=d.length;n--;)if(d[n].href===t)return e();setTimeout((function(){u(e)}))};function h(){s.addEventListener&&s.removeEventListener("load",h),s.media=n||"all"}return s.addEventListener&&s.addEventListener("load",h),s.onloadcssdefined=u,u(h),s}</script><script>loadCSS("https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.14/css/all.min.css",window.volantis.loadcss),loadCSS("https://cdn.jsdelivr.net/gh/l-lin/font-awesome-animation/dist/font-awesome-animation.min.css",window.volantis.loadcss),loadCSS("https://cdn.jsdelivr.net/npm/node-waves@0.7.6/dist/waves.min.css",window.volantis.loadcss)</script><script src="https://cdn.jsdelivr.net/npm/jquery@3.5/dist/jquery.min.js"></script><script>function pjax_fancybox(){$(".md .gallery").find("img").each((function(){var a=document.createElement("a");$(a).attr("class","fancybox"),$(a).attr("pjax-fancybox",""),$(a).attr("href",$(this).attr("src")),$(this).attr("data-original")&&$(a).attr("href",$(this).attr("data-original")),$(a).attr("data-fancybox","images");var t="";$(this).attr("alt")&&($(a).attr("data-caption",$(this).attr("alt")),t=$(this).attr("alt"));var n=document.createElement("div");$(n).addClass("fancybox"),$(this).wrap(n);var o=document.createElement("span");$(o).addClass("image-caption"),$(o).text(t),$(this).after(o),$(this).wrap(a)})),$(".md .gallery").find("img").fancybox({selector:'[data-fancybox="images"]',hash:!1,loop:!1,closeClick:!0,helpers:{overlay:{closeClick:!0}},buttons:["zoom","close"]})}function SCload_fancybox(){0!=$(".md .gallery").find("img").length&&(loadCSS("https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css",document.getElementById("loadcss")),loadScript("https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js",pjax_fancybox))}function Pjax_SCload_fancybox(){void 0===$.fancybox?SCload_fancybox():pjax_fancybox()}$((function(){SCload_fancybox()})),volantis.pjax.push(Pjax_SCload_fancybox),volantis.pjax.send(()=>{void 0!==$.fancybox&&$.fancybox.close()},"fancybox")</script><script src="https://cdn.jsdelivr.net/npm/jquery-backstretch@2.1.18/jquery.backstretch.min.js"></script><script type="text/javascript">var imgs=["https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/001.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/002.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/003.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/004.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/005.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/006.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/012.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/016.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/019.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/033.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/034.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/035.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/038.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/039.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/042.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/046.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/051.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/052.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/054.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/056.jpg"];{function shuffle(t){for(var n=t.length;n--;){var i=Math.floor(Math.random()*n),l=t[i];t[i]=t[n],t[n]=l}}shuffle(imgs)}function Pjax_backstretch(){$("#cover-backstretch").backstretch(imgs,{duration:"10000",fade:"1500"})}loadScript("https://cdn.jsdelivr.net/npm/jquery-backstretch@2.1.18/jquery.backstretch.min.js",Pjax_backstretch)</script><div id="rightmenu-wrapper"><ul class="list-v rightmenu" id="rightmenu-content"><li class="option"><a class="vlts-menu opt fix-cursor-default" id="menu-copy-text" onclick='document.execCommand("copy")'><i class="fa fa-copy fa-fw"></i> 复制文本</a><hr id="hr-text"><a class="vlts-menu opt fix-cursor-default" id="menu-copy-href"><i class="fa fa-link fa-fw"></i> 复制链接</a><a class="vlts-menu opt fix-cursor-default" id="menu-open-href"><i class="fa fa-external-link-square-alt fa-fw"></i> 在新标签页打开</a><hr id="hr-href"><a class="vlts-menu opt fix-cursor-default" id="menu-copy-src"><i class="fa fa-image fa-fw"></i> 复制图片地址</a><hr id="hr-src"></li><li class="navigation"><a class="nav icon-only fix-cursor-default" onclick="history.back()"><i class="fa fa-arrow-left fa-fw"></i></a><a class="nav icon-only fix-cursor-default" onclick="history.forward()"><i class="fa fa-arrow-right fa-fw"></i></a><a class="nav icon-only fix-cursor-default" onclick="window.location.reload()"><i class="fa fa-redo fa-fw"></i></a><a class="nav icon-only fix-cursor-default" href="/"><i class="fa fa-home fa-fw"></i></a></li><hr><li><a class="vlts-menu fix-cursor-default" href="https://volantis.js.org/faqs/" id="https:volantisjsorgfaqs"><i class="fa fa-question fa-fw"></i> 常见问题</a></li><li><a class="vlts-menu fix-cursor-default" href="https://volantis.js.org/examples/" id="https:volantisjsorgexamples"><i class="fa fa-rss fa-fw"></i> 示例博客</a></li><li><a class="vlts-menu fix-cursor-default" href="https://volantis.js.org/contributors/" id="https:volantisjsorgcontributors"><i class="fa fa-fan fa-spin fa-fw"></i> 加入社区</a></li><hr><li><a class="vlts-menu fix-cursor-default" href="https://github.com/volantis-x/volantis-docs/" id="https:githubcomvolantis-xvolantis-docs"><i class="fa fa-code-branch fa-fw"></i> 本站源码</a></li><li><a class="vlts-menu fix-cursor-default" href="https://github.com/volantis-x/hexo-theme-volantis/" id="https:githubcomvolantis-xhexo-theme-volantis"><i class="fa fa-code-branch fa-fw"></i> 主题源码</a></li><hr><li><a class="vlts-menu fix-cursor-default" onclick='document.execCommand("print")'><i class="fa fa-print fa-fw"></i> 打印页面</a></li><hr><li><a class="vlts-menu fix-cursor-default toggle-mode-btn"><i class="fas fa-moon fa-fw"></i> Dark</a></li><hr><li class="music name"><p class="nav music-title fix-cursor-default"></p></li><li class="music ctrl"><a class="nav icon-only backward fix-cursor-default" onclick="aplayerBackward()"><i class="fa fa-step-backward fa-fw"></i></a><a class="nav icon-only toggle fix-cursor-default" onclick="aplayerToggle()"><i class="fa fa-play fa-fw"></i></a><a class="nav icon-only forward fix-cursor-default" onclick="aplayerForward()"><i class="fa fa-step-forward fa-fw"></i></a></li><li class="music volume"><a class="nav volume"><div class="aplayer-volume-bar-wrap"><div class="aplayer-volume-bar fix-cursor-pointer"><div class="aplayer-volume"></div><i class="left fa fa-volume-off fa-fw"></i><i class="right fa fa-volume-up fa-fw"></i></div></div></a></li></ul></div><script>function popMenu(e){var t=document.getElementById("rightmenu-wrapper"),n=document.getElementById("rightmenu-content"),l=document.documentElement.clientWidth||document.body.clientWidth,o=document.documentElement.clientHeight||document.body.clientHeight;t.style.left=e.clientX+"px",t.style.top=e.clientY+"px",t.style.display="block",2*e.clientX>l?n.classList.add("left"):n.classList.remove("left"),2*e.clientY>o?n.classList.add("top"):n.classList.remove("top");let c=document.getElementById("hr-text"),d=document.getElementById("hr-src"),y=document.getElementById("hr-href"),s=document.getElementById("menu-copy-src");null!=s&&(e.target.currentSrc?(s.style.display="block",s.addEventListener("click",(function(t){copyString(e.target.currentSrc)}),{once:!0}),d.style.display="block"):(s.style.display="none",d.style.display="none"));let r="";if(e.path)for(i=0;i<e.path.length;i++)null!=e.path[i].href&&e.path[i].href.length>0&&(r=e.path[i].href);let u=document.getElementById("menu-copy-text");u.style.display="none",c.style.display="none",0==r.length&&window.getSelection().toString()&&(u.style.display="block",c.style.display="block");let m=document.getElementById("menu-open-href");null!=m&&(r.length>0?(m.style.display="block",m.addEventListener("click",(function(e){window.open(r)}),{once:!0}),y.style.display="block"):(m.style.display="none",y.style.display="none"));let a=document.getElementById("menu-copy-href");return null!=a&&(r.length>0?(a.style.display="block",a.addEventListener("click",(function(e){copyString(r)}),{once:!0})):a.style.display="none"),volantis.APlayerLoaded&&checkAPlayer(),!1}function hideMenu(){document.getElementById("rightmenu-wrapper").style.display="none"}function copyString(e){const t=document.createElement("input");t.setAttribute("readonly","readonly"),document.body.appendChild(t),t.setAttribute("value",e),t.select(),document.execCommand("copy"),document.body.removeChild(t)}window.document.oncontextmenu=function(e){return!!e.ctrlKey||(!!/Android|webOS|BlackBerry/i.test(navigator.userAgent)||popMenu(e))},document.addEventListener("click",(function(e){document.getElementById("rightmenu-wrapper").style.display="none"})),document.execCommand("click")</script><script>function loadIssuesJS(){0!=$(".md").find(".issues-api").length&&loadScript("https://cdn.jsdelivr.net/npm/hexo-theme-volantis@4.3.1/source/js/issues.min.js")}$((function(){loadIssuesJS()})),volantis.pjax.push(()=>{"undefined"==typeof IssuesAPI&&loadIssuesJS()},"IssuesJS")</script><script defer="defer" src="https://cdn.jsdelivr.net/npm/vanilla-lazyload@17.1.0/dist/lazyload.min.js"></script><script>window.lazyLoadOptions={elements_selector:".lazyload",threshold:0},window.addEventListener("LazyLoad::Initialized",(function(n){window.lazyLoadInstance=n.detail.instance}),!1),document.addEventListener("DOMContentLoaded",(function(){lazyLoadInstance.update()})),document.addEventListener("pjax:complete",(function(){lazyLoadInstance.update()}))</script><script>window.FPConfig={delay:0,ignoreKeywords:[],maxRPS:5,hoverDelay:25}</script><script defer="defer" src="https://cdn.jsdelivr.net/gh/gijo-varghese/flying-pages@2.1.2/flying-pages.min.js"></script><script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script><script>var clipboard=new ClipboardJS(".btn-copy",{target:function(e){return e.nextElementSibling}});function wait(e,i){window.setTimeout(e,i)}function pjax_initCopyCode(){if($(".highlight .code pre").length+$(".article pre code").length!=0){var e="";e+='<button class="btn-copy" data-clipboard-snippet="">',e+='<i class="fas fa-copy"></i><span>COPY</span>',e+="</button>",$(".highlight .code pre").before(e),$(".article pre code").before(e),clipboard.off("success").on("success",(function(e){let i=$(e.trigger);i.addClass("copied");let a=$(i.find("i"));a.removeClass("fa-copy"),a.addClass("fa-check-circle");let n=$(i.find("span"));n[0].innerText="COPIED",wait((function(){a.removeClass("fa-check-circle"),a.addClass("fa-copy"),n[0].innerText="COPY"}),2e3)})),clipboard.off("error").on("error",(function(e){e.clearSelection();let i=$(e.trigger);i.addClass("copy-failed");let a=$(i.find("i"));a.removeClass("fa-copy"),a.addClass("fa-times-circle");let n=$(i.find("span"));n[0].innerText="COPY FAILED",wait((function(){a.removeClass("fa-times-circle"),a.addClass("fa-copy"),n[0].innerText="COPY"}),2e3)}))}}$((function(){pjax_initCopyCode()})),volantis.pjax.push(pjax_initCopyCode)</script><script type="text/javascript">function pjax_scrollrebeal(){ScrollReveal().reveal(".l_main .reveal",{distance:"32px",duration:"800",interval:"20",scale:"1",easing:"ease-out"})}loadScript("https://cdn.jsdelivr.net/npm/scrollreveal@4.0.6/dist/scrollreveal.min.js"),$((function(){var e=setInterval((function(){"block"==$("#safearea").css("display")&&"undefined"!=typeof ScrollReveal&&(clearInterval(e),pjax_scrollrebeal())}),100)})),volantis.pjax.push(pjax_scrollrebeal)</script><script>let APlayerController=new Object;APlayerController.id="5472211102",APlayerController.volume="0.7",loadCSS("https://cdn.jsdelivr.net/npm/aplayer@1.10/dist/APlayer.min.css",window.volantis.loadcss),loadScript("https://cdn.jsdelivr.net/npm/aplayer@1.10/dist/APlayer.min.js"),window.volantis.APlayerLoaded=0;var checkAPlayer=setInterval((function(){window.APlayer&&"block"==$("#safearea").css("display")&&(clearInterval(checkAPlayer),window.volantis.APlayerLoaded||window.MetingJSElement||(window.volantis.APlayerLoaded=1,loadScript("https://cdn.jsdelivr.net/npm/meting@2.0/dist/Meting.min.js")))}),2500);loadScript("https://cdn.jsdelivr.net/npm/hexo-theme-volantis@4.3.1/source/js/aplayer.min.js")</script><script src="https://cdn.jsdelivr.net/npm/hexo-theme-volantis@4.3.1/source/js/valine.min.js"></script><script>function emoji(i,e,a){return i+"/"+i+"-"+e+"."+a}for(var emojiMaps={},i=1;i<=54;i++)emojiMaps["tieba-"+i]=emoji("tieba",i,"png");for(i=1;i<=101;i++)emojiMaps["qq-"+i]=emoji("qq",i,"gif");for(i=1;i<=116;i++)emojiMaps["aru-"+i]=emoji("aru",i,"gif");for(i=1;i<=125;i++)emojiMaps["twemoji-"+i]=emoji("twemoji",i,"png");for(i=1;i<=4;i++)emojiMaps["weibo-"+i]=emoji("weibo",i,"png");function pjax_valine(){if(!document.querySelectorAll("#valine_container")[0])return;let i=pdata.commentPlaceholder||"快来评论吧~",e=pdata.commentPath;if(0==e.length){e=""||decodeURI(window.location.pathname)}(new Valine).init(Object.assign({path:null,placeholder:"快来评论吧~",appId:"eL9fCmXLl3nAe225XYo1cRxj-MdYXbMMI",appKey:"5uTd5Uu8WJJIej6Efrivsvaa",meta:["nick","mail","link"],requiredFields:["nick","mail"],enableQQ:!0,recordIP:!1,avatar:"robohash",pageSize:10,lang:"zh-cn",highlight:!0,mathJax:!1},{el:"#valine_container",path:e,placeholder:i,emojiCDN:"https://cdn.jsdelivr.net/gh/volantis-x/cdn-emoji/valine/",emojiMaps:emojiMaps}))}$((function(){pjax_valine()})),volantis.pjax.push(pjax_valine)</script><script defer="defer" src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-busuanzi@2.3/js/busuanzi.pure.mini.js" data-pjax></script><script src="https://cdn.jsdelivr.net/npm/hexo-theme-volantis@4.3.1/source/js/app.min.js"></script><script>const SearchServiceimagePath="https://cdn.jsdelivr.net/gh/volantis-x/cdn-volantis@master/img/",ROOT="/".endsWith("/")?"/":"//";function listenSearch(){customSearch=new HexoSearch({imagePath:SearchServiceimagePath})}function setSearchService(){listenSearch()}$(".input.u-search-input").one("focus",(function(){loadScript("https://cdn.jsdelivr.net/gh/volantis-x/cdn-volantis@2.6.4/js/search.js",setSearchService)}))</script><script src="https://cdn.jsdelivr.net/npm/node-waves@0.7.6/dist/waves.min.js"></script><script type="text/javascript">$((function(){Waves.attach(".flat-btn",["waves-button"]),Waves.attach(".float-btn",["waves-button","waves-float"]),Waves.attach(".float-btn-light",["waves-button","waves-float","waves-light"]),Waves.attach(".flat-box",["waves-block"]),Waves.attach(".float-box",["waves-block","waves-float"]),Waves.attach(".waves-image"),Waves.init()}))</script><script src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-volantis@2/js/comment_typing.js"></script><script defer="defer">const LCCounter={app_id:"C2dIVXJ48qC7eHgvQRId6niR-MdYXbMMI",app_key:"1956OGJ4LQhDxheBAO5WhPJn",custom_api_server:"",getRecord:(e,t,r)=>new Promise((function(n,i){e("get","/classes/Counter?where="+encodeURIComponent(JSON.stringify({url:t}))).then(e=>e.json()).then(({results:o,code:s,error:a})=>{if(401===s)throw a;if(o&&o.length>0){var l=o[0];n(l)}else e("post","/classes/Counter",{url:t,title:r,times:0}).then(e=>e.json()).then((e,t)=>{if(t)throw t;n(e)}).catch(e=>{console.error("Failed to create",e),i(e)})}).catch(e=>{console.error("LeanCloud Counter Error:",e),i(e)})})),increment:(e,t)=>new Promise((function(r,n){e("post","/batch",{requests:t}).then(e=>{if((e=e.json()).error)throw e.error;r(e)}).catch(e=>{console.error("Failed to save visitor count",e),n(e)})})),buildIncrement:e=>({method:"PUT",path:"/1.1/classes/Counter/"+e,body:{times:{__op:"Increment",amount:1}}}),validUV(){var e="LeanCloudUVTimestamp",t=localStorage.getItem(e);return!(t&&(new Date).getTime()-parseInt(t)<=864e5)&&(localStorage.setItem(e,(new Date).getTime().toString()),!0)},addCount(e){var t=[],r=[],n=document.querySelector("#lc-sv"),o=this.getRecord(e,"http://aner1001.gitee.io/#lc-sv","Visits").then(e=>{r.push(this.buildIncrement(e.objectId));var t=document.querySelectorAll("#lc-sv #number");t.length>0&&t.forEach((t,r,i)=>{t.innerText=e.times+1,n&&(n.style.display="inline")})});t.push(o);var s=document.querySelector("#lc-uv"),a=this.getRecord(e,"http://aner1001.gitee.io/#lc-uv","Visitors").then(e=>{var t=this.validUV();t&&r.push(this.buildIncrement(e.objectId));var n=document.querySelectorAll("#lc-uv #number");n.length>0&&n.forEach((r,n,i)=>{r.innerText=e.times+(t?1:0),s&&(s.style.display="inline")})});t.push(a);var l=document.querySelectorAll("#lc-pv");for(l.length,i=0;i<l.length;i++){let n=l[i],o=n.getAttribute("data-title");var h="http://aner1001.gitee.io"+n.getAttribute("data-path");if(h){var c=this.getRecord(e,h,o).then(e=>{let t=window.location.pathname;if(t.includes("index.html")&&(t=t.substring(0,t.lastIndexOf("index.html"))),n.getAttribute("data-path")==t&&r.push(this.buildIncrement(e.objectId)),n){var i=n.querySelector("#lc-pv #number");i&&(n.getAttribute("data-path")==t?i.innerText=(e.times||0)+1:i.innerText=e.times||0,n.style.display="inline")}});t.push(c)}}Promise.all(t).then(()=>{r.length>0&&this.increment(e,r)})},fetchData(e){this.addCount((t,r,n)=>fetch(`${e}/1.1${r}`,{method:t,headers:{"X-LC-Id":this.app_id,"X-LC-Key":this.app_key,"Content-Type":"application/json"},body:JSON.stringify(n)}))},refreshCounter(){var e="-MdYXbMMI"!==this.app_id.slice(-9)?this.custom_api_server:`https://${this.app_id.slice(0,8).toLowerCase()}.api.lncldglobal.com`;e?this.fetchData(e):fetch("https://app-router.leancloud.cn/2/route?appId="+this.app_id).then(e=>e.json()).then(({api_server:e})=>{this.fetchData("https://"+e)})}};LCCounter.refreshCounter(),document.addEventListener("pjax:complete",(function(){LCCounter.refreshCounter()}))</script><script>const rootElement=document.documentElement,darkModeStorageKey="user-color-scheme",rootElementDarkModeAttributeName="data-user-color-scheme",setLS=(e,t)=>{localStorage.setItem(e,t)},removeLS=e=>{localStorage.removeItem(e)},getLS=e=>localStorage.getItem(e),getModeFromCSSMediaQuery=()=>window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light",resetRootDarkModeAttributeAndLS=()=>{var e;rootElement.removeAttribute("data-user-color-scheme"),e=darkModeStorageKey,localStorage.removeItem(e)},validColorModeKeys={dark:!0,light:!0},applyCustomDarkModeSettings=e=>{const t=e||getLS(darkModeStorageKey);t===getModeFromCSSMediaQuery()?resetRootDarkModeAttributeAndLS():validColorModeKeys[t]?rootElement.setAttribute("data-user-color-scheme",t):resetRootDarkModeAttributeAndLS()},invertDarkModeObj={dark:"light",light:"dark"},toggleCustomDarkMode=()=>{let e=getLS(darkModeStorageKey);if(validColorModeKeys[e])e=invertDarkModeObj[e];else{if(null!==e)return;e=invertDarkModeObj[getModeFromCSSMediaQuery()]}var t,o;return t=darkModeStorageKey,o=e,localStorage.setItem(t,o),e};var btn=$("#wrapper .toggle-mode-btn,#rightmenu-wrapper .toggle-mode-btn");function bindToggleButton(){btn.on("click",e=>{const t=toggleCustomDarkMode();applyCustomDarkModeSettings(t)})}applyCustomDarkModeSettings(),document.addEventListener("DOMContentLoaded",bindToggleButton),volantis.pjax.push(bindToggleButton),volantis.pjax.send(()=>{btn.unbind("click")},"toggle-mode-btn-unbind")</script><script>function listennSidebarTOC(){const e=document.querySelectorAll(".toc li");if(!e.length)return;const t=[...e].map(e=>{const t=e.querySelector(".toc-link"),n=document.getElementById(decodeURI(t.getAttribute("href")).replace("#",""));return t.addEventListener("click",e=>{e.preventDefault(),window.scrollTo({top:n.offsetTop+100,behavior:"smooth"})}),n});!function n(o){o=Math.floor(o+1e4);let r=new IntersectionObserver((r,c)=>{let i=document.documentElement.scrollHeight+100;if(i>o)return c.disconnect(),void n(i);let l=function(e){let n=0,o=e[n];if(o.boundingClientRect.top>0)return n=t.indexOf(o.target),0===n?0:n-1;for(;n<e.length;n++){if(!(e[n].boundingClientRect.top<=0))return t.indexOf(o.target);o=e[n]}return t.indexOf(o.target)}(r);!function(e){if(e.classList.contains("active-current"))return;document.querySelectorAll(".toc .active").forEach(e=>{e.classList.remove("active","active-current")}),e.classList.add("active","active-current");let t=e.parentNode;for(;!t.matches(".toc");)t.matches("li")&&t.classList.add("active"),t=t.parentNode}(e[l])},{rootMargin:o+"px 0px -100% 0px",threshold:0});t.forEach(e=>{e&&r.observe(e)})}(document.documentElement.scrollHeight)}document.addEventListener("DOMContentLoaded",listennSidebarTOC),document.addEventListener("pjax:success",listennSidebarTOC)</script><script>"serviceWorker"in navigator&&navigator.serviceWorker.register("/sw.js").then((function(e){e.onupdatefound=function(){var r=e.installing;r.onstatechange=function(){switch(r.state){case"installed":navigator.serviceWorker.controller?console.log("Updated serviceWorker."):console.log("serviceWorker Sucess!");break;case"redundant":console.log("The installing service worker became redundant.")}}}})).catch((function(e){console.log("Error during service worker registration:",e)}))</script><script src="https://cdn.jsdelivr.net/npm/pjax@0.2.8/pjax.min.js"></script><div class="pjax-animate"><script src="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.js"></script><div id="loading-bar-wrapper"><script>NProgress.configure({parent:"#loading-bar-wrapper",trickleSpeed:100})</script></div><script>window.ShowLoading=function(){NProgress.start()},window.HideLoading=function(){NProgress.done()}</script><script>volantis.pjax.push(window.HideLoading,"HideLoading"),volantis.pjax.send(window.ShowLoading,"ShowLoading"),volantis.pjax.error(window.HideLoading,"HideLoading")</script></div><script>var pjax;document.addEventListener("DOMContentLoaded",(function(){pjax=new Pjax({elements:'a[href]:not([href^="#"]):not([href="javascript:void(0)"]):not([pjax-fancybox])',selectors:["title","#pjax-container","#pjax-header-nav-list"],cacheBust:!1,timeout:5e3})})),document.addEventListener("pjax:send",(function(e){try{var n=window.location.pathname,t=e.triggerElement.href,o=[""];""!=o[0]&&o.forEach(e=>{-1==n.indexOf(e)&&-1==t.indexOf(e)||(window.location.href=t)})}catch(e){}window.subData=null,volantis.$switcher.removeClass("active"),volantis.$header.removeClass("z_search-open"),volantis.$wrapper.removeClass("sub"),volantis.$topBtn.unbind("click"),$(".menu a").unbind("click"),$(window).unbind("resize"),$(window).unbind("scroll"),$(document).unbind("scroll"),$(document).unbind("click"),$("body").unbind("click"),volantis.pjax.method.send.start()})),document.addEventListener("pjax:complete",(function(){$(".nav-main").find(".list-v").not(".menu-phone").removeAttr("style",""),$(".menu-phone.list-v").removeAttr("style",""),$("script[data-pjax], .pjax-reload script").each((function(){$(this).parent().append($(this).remove())}));try{volantis.pjax.method.complete.start()}catch(e){console.log(e)}})),document.addEventListener("pjax:error",(function(e){volantis.pjax.method.error.start(),window.location.href=e.triggerElement.href}))</script></div></body></html>